Moonfish

Moonfish, Drepane punctata

Contents

License

Moonfish is copyright © 2006 Alex Waugh

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Introduction

Moonfish is an NFS server, that can be used to share files to another computer. It has been tested with clients including Linux 2.4, Solaris 8, Windows Services for UNIX 3.5, and Sunfish on RISC OS, but should work with any suitable NFS client on any platform. The server supports version 2, version 3, or version 4 of the NFS protocol, version 1 or 3 of the Mount protocol, and version 2 of the portmapper protocol. Both UDP and TCP connections are supported. Authentication and encryption with the auth_gss method of NFS4 are not currently supported.

It runs as a module in the background, and so can continue to serve files even when the machine is single tasking.

Moonfish should run on any version of RISC OS from 3.11 onwards, although it has only been tested on RISC OS 4 and RISC OS 5. It is 26/32bit neutral, and requires a 32bit Shared C Library that includes C99 features.

Any updates will be available from http://www.alexwaugh.com/

Installing

Moonfish can either be installed as a configure plugin (RISC OS 4 onwards) or it can be used standalone. The former is recommended if possible.

To install as a configure plugin, copy the !Moonfish directory into !Boot.Resources.Configure, then when you run configure by double clicking on !Boot you should get a Moonfish icon in the configure window.

To use standalone, simply copy !Moonfish to whereever you want, then double click on it to load it. It will put an icon on the iconbar, clicking on which will open the exports window. The autoload module option is not available when run standalone, but the exports window is otherwise identical to when run as a configure plugin.

Moonfish requires the Iconv module to be installed. This can be downloaded from here.

Loading the module

The actual server is provided by the Moonfish module, and so this needs to be loaded for clients to be able to access any of the exports. The module is loaded whenever !Moonfish is run, either standalone or from configure, and remains loaded even when the GUI is quit.

If you want the module loaded when the machine is booted (so that the exports are always available to clients) then you can set the autoload at boot option which will create a file in !Boot.Choices.Boot.Tasks (or whatever the equivalent directory is) which will load just the Moonfish module when the machine is booted. If you are not using Moonfish as a configure plugin then this option is not available and you will have to ensure the module is loaded some other way, for example by adding the !Moonfish application to the list of tasks to run in the boot sequence configuration.

Export Options

In the exports window, there is a list of directories to export (initially this will be blank). You can select a directory from the list and edit or delete it using the respective buttons to the right. To add a new directory to the list, click on the Add button and fill in the details in the edit export window. All fields in the edit export window must be filled in for a working export to be set up, however those in the options window can often be left as the defaults.

Directory

Specifies the directory to export. This can be any directory on a local filing system, including a root directory of a disc. You can drag a directory from the filer onto this field to fill in the icon.

Export

This is the name to export the directory as, and will be what client machines will see as the name of the export. It can be the same as the leafname of the directory, or it can be different. It is recommend that the name starts with a / and contains only alphanumeric and underscore character, as some clients may expect it to be in the format of a Unix path, for example /home.

Allow connections from

This allows you to limit the client machines that are allowed to access the export. It can be specified as a hostname or IP address of a single machine, an IP address and netmask to allow a range of IP addresses (e.g. 192.168.0.0/24 to allow any address in the range 192.168.0.0 to 192.168.0.255), or it can be * to allow access from any address. If allowing any address to access the server, it is strongly recommeded that you use some sort of firewall to prevent access from unwanted machines.

Optional options

These options can be specified from the options window if needed, but if they are not then default values will be used. For many cases the defaults will be sufficient.

UID

The UID to report all files and directories belong to. If left blank, the UID used will be whatever the client reports its UID as.

GID

The GID to report all files and directories belong to. If left blank, the GID used will be whatever the client reports its primary GID as.

UDP transfer size

The maximum number of bytes to use for the data buffer of a read or write request on UDP transfers. A bigger buffer will generally be faster than a smaller one on a fast machine such as an Iyonix, but on slower machines like RiscPCs (particularly when the client is faster than the server) a larger buffer will cause more packets to get lost and hence slow things down. The maximum value is 8192 bytes, and it is recommeded that you set it to this if your network card can handle it (You will probably get timeout errors or very slow file transfer when reading files if it is too big). If omitted, it defaults to 4096 bytes.

Read only

If set the export will be marked as read only, and any writes will be prevented.

Fake directory timestamps

On Unix like filesystems, the timestamp of a directory gets updated whenever the contents of a directory are altered, e.g. a new file is added to the directory. Some clients will cache the contents of directories to improve performance, and use the timestamp of the directory to determine whether the cache is out of date or not. However RISC OS does not update the timpstamp of the directory when you add or delete a file from it, and so such a caching system will not update its cache correctly. If this option is set, the timestamp of all directories are reported as the current time, so that any cache will always get updated (although this negates some of the benefit of caching).

This setting is ignored for NFSv4 exports, as NFSv4 has an explicit changeid attribute to determine if a directory has changed.

Treat image filing systems as directories

By default, image files (e.g. zip files when SparkFS is loaded) will be reported as files. If this option is set then they will be treated as directories, and so the client will not realise that they are actually files, and can manipulate the contents.

umask

The umask to use, specified in octal. All operations that return a file's attributes will have the Unix mode bits modified according to the umask. If not specified, it defaults to 0, and the mode bits are not modified.

unumask

RISC OS does not have any concept like a umask - the default attributes of a file are decided by the application that creates the file. Usually the default chosen is private read/write set and public read/write clear, although sometimes private read/write is not set either, which doesn't have any effect on RISC OS applications accessing the files, but can prevent Unix applications from accessing them. The unumask allows you to force particular unix mode bits to be set, and is specified in octal in the same format as the umask. If not specified, it defaults to 0.

The RISC OS attributes are first converted to unix mode bits, with the private attributes mapping to user permissions, and the public attributes mapping to the group and others permissions (if a public attribute is set then both the corresponding group and others permission bit will be set). If the object is a directory then execute permissions will be set if the corresponding read permission is set. This value is then ORed with the unumask, and then ANDed with the inverse of the umask to give the final unix mode bits.

DefaultFiletype

The hexadecimal filetype to give a file if it doesn't have an ,xyz filetype extension or a . extension that matches a mimemap entry. If not specified then it defaults to FFF.

Add extension

Controls adding of a ,xyz filetype extension. When set to never, no ,xyz extensions are added, and all files get the default filetype. When set to only when needed, an ,xyz extension is only added when necessary to preserve the filetype, and if the file has a . extension that matches a mimemap entry then no extension is added. When set to always, an ,xyz extension is always added.

Global Choices

UDP

Enable connections over the UDP transport. This is what has been traditionally used for NFSv2 and NFSv3 connections.

TCP

Enable connections over the TCP transport. This is what is normally used for NFSv4 connections. Note that the portmapper, if enabled, will always listen on both TCP and UDP, regardless of the settings here.

Encoding

The client machine may be set to a different locale than the server, and so filenames may be encoded in a different character set on one machine to the other. NFSv4 specifies that filenames must be encoded as UTF-8, so Moonfish will automatically convert the local filenames to UTF-8 (It assumes that they are encoded on the local disc in the same encoding as the alphabet set with *alphabet).

For NFSv2 and NFSv3, it is not specified what encoding the filenames should be in. Therefore this option allows you to specify the encoding to be used for NFSv2 and NFSv3. The value can be any encoding that the iconv module understands. If left blank, no encoding conversion is done.

Portmapper

Enables the portmapper, listening on port 111. This must be selected if either NFSv2 or NFSv3 is enabled.

NFS v2 and Mount v1

Enables the NFSv2 protocol, and the associated Mount v1 protocol.

NFS v3 and Mount v3

Enables the NFSv3 protocol, and the associated Mount v3 protocol.

NFS v4

Enables the NFSv4 protocol, listening on port 2049. The portmapper and mount protocols are not needed for NFSv4.

Autoload module at boot

When set, this option creates a file in !Boot.Choices.Boot.Tasks (or equivalent) to load the Moonfish module when the machine is booted. This option will be unavailable unless you are running Moonfish as a configure plugin.

Ignore extensions of resource forks

When set, the filetype of files with a filename beginning with "._" (as typically used to hold MacOS resource forks) is set to data, rather than being based on the filename extension. Filenames with an explicit ,xyz extention will still get the filetype specified.

Improving Performance

There are three options that are likely to have an effect on performance, although only the first one is under the control of the server, the other two you have to specify on the client.

Reporting Bugs

If you discover a bug, please report it to me, or better still fix it yourself and send me a patch. When reporting a bug, first make sure SysLog is loaded, and check the Moonfish log if it exists for any error messages. If you have access to a machine that can run a packet sniffer such as ethereal then it would be very useful to use that to save a dump of the network traffic along with the syslog file. Also, please provide a description of the problem and exactly what operation you were doing to trigger the bug, and details of what OS and NFS version the client is running would be helpful, and the version of the Moonfish module and RISC OS version.

Known Issues

Each file should have a unique ID associated with it (the inode on a Unix system), but RISC OS does not provide a method for generating this, therefore it is calculated as a hash of the filename. While this will be unique in most cases, it is possible for two files to end up with the same ID. This could be an issue if a client relies on the uniqueness of the ID, but it has not yet been observed as a problem in practice.

NFS refers to files by an NFS filehandle, and Moonfish must be able to map an NFS filehandle onto a RISC OS filename. For filenames that are less than 32 (NFS2), 64 (NFS3), or 128 (NFS4) characters this is easy as the filename can be stored fully in the filehandle. However for filenames longer than this, Moonfish must maintain a cache of the mappings from filehandle to filename. Therefore if you access lots of different files with long filenames then this cache will grow and use more memory. The format of the cache imposes a limit on the number of directory levels supported (30 for NFS2, 62 for NFS3, 126 for NFS4) but this is unlikely to be an issue.

For NFS2 and NFS3, filehandles are supposed to be persistant, so if the server is restarted or rebooted the filehandle should remain valid and point to the same file. However because Moonfish maintains the cache to map filehandles to filenames, this cache is lost when Moonfish exits, and so the mapping is no longer valid. Most clients will reread the filehandle if it becomes stale, and so can cope with this situation. This is not an issue with NFS4 as that allows filehandles to be volatile.

Hard links, symbolic links, devices and other non regular files are not supported, as they don't map to RISC OS functionality.

File permissions behave slightly differently from Unix systems. For example if the client copies a file that has only user read permission onto the export then it may create the file with user read permission, then write to the file. On some systems this write is allowed, but with RISC OS the write is faulted because the file does not have user write permissions.

The code is currently optimised for performance of the file transfers, at the expense of slowing the desktop down when large transfers are taking place. If there is demand I may add an option to try an keep the desktop more responsive, although this would of course reduce the speed of file transfers.

NFSv4 mandates that implementations support the auth_gss method of authenticating and encrypting using Kerberos V5 and LIPKEY. Moonfish does not currently support this.

Recompiling

Full source code is provided. To recompile the module, you will need at least either GCC 3.4.4 release 3 or Norcroft v5.53, cmhg or CMunge, TCPIPLibs, GNU make, and Perl. Earlier 26bit versions of Norcroft will not work because the code makes use of 64bit integers and some C99 functions.

The makefile in the src directory has several targets: